<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
<script>
    //一、元字符是拥有特殊含义的字符

    // . 点符号 —— 匹配任意单个字符，换行符除外。
    var pattern = /box./ig;
    var str = 'This is a box\nThat is a Box too！\nThis is a box\nThat is a Box too！';
    console.log(str);
    console.log(str.replace(pattern, "1234"));
    // This is a box
    // That is a Box too！
    // This is a box
    // That is a Box too！

    // This is a box
    // That is a 1234too！ 将Box(空格)->1234
    // This is a box
    // That is a 1234too！ 将Box(空格)->1234

    //  \w	  匹配字母、数字、下划线。
    var pattern = /\w/ig;
    //var pattern = /\w\w\w/ig;//结果是什么
    // //$$bc@qq.$  $ss-$e $$$e (三个一组)
    var str = '12345abc@qq.com  class-name class_name';
    console.log(str);
    // 12345abc@qq.com  class-name class_name
    console.log(str.replace(pattern, "$"));
    // $$$$$$$$@$$.$$$  $$$$$-$$$$ $$$$$$$$$$

    //  \W	  匹配非字母、数字、下划线。
    var pattern = /\W/ig;
    var str = '12345abc@qq.com  class-name class_name';
    console.log(str);
    // 12345abc@qq.com  class-name class_name
    console.log(str.replace(pattern, "$"));
    // 12345abc$qq$com$$class$name$class_name

    //  \d	  匹配数字。
    var pattern = /\d/g;
    // var pattern = /\d\d/g;
    // //$$5abc@qq.com  class-name
    var str = '12345abc@qq.com  class-name';
    console.log(str);
    console.log(str.replace(pattern, "$"));
    // $$$$$abc@qq.com  class-name

    //  \D	  匹配非数字。
    var pattern = /\D/g;
    var str = '12345abc@qq.com  class-name';
    console.log(str);
    console.log(str.replace(pattern, "$"));
    // 12345$$$$$$$$$$$$$$$$$$$$$$

    //  \s	  匹配空格字符（包括空格和换行空格）。
    var pattern = /\s/g;
    var str = 'This is a box!\nThat is a Box too！\nThat is a Box too too！';
    console.log(str);
    // This is a box!
    // That is a Box too！
    // That is a Box too too！
    console.log(str.replace(pattern, "$"));
    // This$is$a$box!$That$is$a$Box$too！$That$is$a$Box$too$too！
    
    //  \S	  匹配非空格字符。
    var pattern = /\S/g;
    var str = 'This is a box!\nThat is a Box too！\nThat is a Box too too！';
    console.log(str);
    console.log(str.replace(pattern, "$"));
    // $$$$ $$ $ $$$$
    // $$$$ $$ $ $$$ $$$$
    // $$$$ $$ $ $$$ $$$ $$$$

    //  \n	  匹配换行符。
    var pattern = /\n/g;
    var str = 'This is a box!\nThat is a Box too！\nThat is a Box too too！';
    console.log(str);
    console.log(str.replace(pattern, "$"));
    // This is a box!$That is a Box too！$That is a Box too too！
    


    // 二、锚字符
    // 1、 ^ 匹配字符串的开头  注意全局匹配模式
    //var pattern = /^this/;
    //var pattern = /^this/i;
    //var pattern = /^this/g;
    //var pattern = /^this/gi;
    //var pattern = /^this/m;
    //var pattern = /^this/igm;
    var str = 'This is a box! this is a Box too！\nthis is a box! This is a Box too！';
    var newStr = str.replace(pattern,"1234");
    console.log(str);
    console.log(newStr);

    //var pattern = /^this/;
    // This is a box! this is a Box too！ 
    // this is a box! This is a Box too

    //var pattern = /^this/i;
    // 1234 is a box! this is a Box too！
    // this is a box! This is a Box too！

    //var pattern = /^this/g;
    // This is a box! this is a Box too！
    // this is a box! This is a Box too！

    //var pattern = /^this/gi;
    // 1234 is a box! this is a Box too！
    // this is a box! This is a Box too！

    //var pattern = /^this/m;
    // This is a box! this is a Box too！
    // 1234 is a box! This is a Box too！

    //var pattern = /^this/igm;
    // 1234 is a box! this is a Box too！
    // 1234 is a box! This is a Box too！

    // ^ —— 从字符串的开头开始匹配，即 从左向右匹配
    // 示例：验证 URI 是否遵循 https 协议
    var url1 = "https://www.baidu.com/";
    var url2 = "http://www.baidu.com/https";

    function https(url) {
      var pattern = /^https/; //这里填写？？？
      return pattern.test(url);
    }
    console.log(https(url1)); //t
    console.log(https(url2)); //f

    // 2、 $ 匹配字符串的结尾  注意全局匹配模式
    //var pattern = /too!$/;
    //var pattern = /too!$/m;
    //var pattern = /too!$/mg;
    var str = 'This is a box! this is a Box too!\nthis is a box! This is a Box too!';
    console.log(str.replace(pattern, "1234"));
    
    //var pattern = /too!$/;
    // This is a box! this is a Box too!
    // this is a box! This is a Box 1234

    //var pattern = /too!$/m;
    // This is a box! this is a Box 1234
    // this is a box! This is a Box too!

    //var pattern = /too!$/mg;
    // This is a box! this is a Box 1234
    // this is a box! This is a Box 1234

    // $ —— 从字符串的结尾开始匹配，即从右向左匹配
    // 示例：验证文件是否是 css 文件
    var file1 = "css.js";
    var file2 = "js.css";

    function css(filename) {
        var pattern = /css$/; //这里填写？？？
        return pattern.test(filename);
    }
    console.log(css(file1)); //f
    console.log(css(file2)); //t

    // 3、边界\b \B
    //边界:是指一个位置，而不是某一个具体的字符，那什么是位置，那就是每个单词之间以及字符串首尾
   
    //3(1)、 \b 匹配字符串的边界  开头或者结尾
    //var pattern = /8\b/mg;
    //var pattern = /\b8/mg;
    var str = '8pattern8\n8pattern8';
    console.log(str.replace(pattern, "$"));

    //var pattern = /8\b/mg;
    // 8pattern$
    // 8pattern$

    //var pattern = /\b8/mg;
    // $pattern8
    // $pattern8

    //3(2)、 \B 匹配字符串的非边界
    var pattern = /\B8/g;
    var str = '8pattern8-8pattern8';
    //var str = '8pattern8_8pattern8'; //8pattern$_$pattern$
    console.log(str.replace(pattern, "$"));
    // 8pattern$-8pattern$

    var pattern = /8\B/g;
    var str = '8pattern8-8pattern8';
    //var str = '8pattern8_8pattern8'; //8pattern$-8pattern$
    console.log(str.replace(pattern, "$"));
    // $pattern8-$pattern8

    // 将文本中的单词 cat 换成 dog
    var sentence = "You shouldn't let that cat scattered kids' food all over the room.";
    var pattern = /cat/g; //scattered->sdogtered
    var pattern = /\bcat\b/g; //两边的空格是边界
    sentence.replace(pattern, "dog");
    // "You shouldn't let that dog scattered kids' food all over the room."

    // 4、零宽断言
    // (?=exp)匹配其后紧接 exp 的字符串
    //  零宽正向先行断言，要求接下来的字符都与  exp  匹配，但不包括 匹配 exp 的那些字符
    var pattern = /java/ig; //$Script is different from $!
    //var pattern = /java(?=script)/ig; //匹配java前提是后面是script字符串
    //$Script is different from Java!
    var str = "JavaScript is different from Java!";
    console.log(str.replace(pattern, "$"));

    // (?!exp)匹配其后没有紧接 exp 的字符串
    //   零宽负向先行断言，要求接下来的字符都与  exp  不匹配
    var pattern = /java(?!script)/ig;
    var str = "JavaScript is different from Java!";
    console.log(str.replace(pattern, "$"));
    // JavaScript is different from $!

    // 5、方括号
    //单词:是指由\w即[a-zA-Z0-9_]组成的字符串(字母数字下划线)
    // 方括号用于查找某个范围内的字符

    //匹配[]方括号字符集中的任何字符。
    var pattern = /[abc]/ig;  //a或b或c
    // var pattern = /[bt]/ig; //b或t
    // var pattern = /[bt]o/ig;  //bo或to
    var str = 'This is a box! this is a Box too!';
    console.log(str);
    console.log(str.replace(pattern, "$"));
    //This is $ $ox! this is $ $ox too!
    //$his is a $ox! $his is a $ox $oo!
    //This is a $x! this is a $x $o!

    // [^]匹配任何不在方括号字符集中的任意字符。
    var pattern = /[^abc]/ig; //只有不是a或者b或者c的
    var str = 'This is a box! this is a Box too!';
    console.log(str);
    console.log(str.replace(pattern, "$"))
    // $$$$$$$$a$b$$$$$$$$$$$$a$B$$$$$$$

    console.log("absxsdfe1Q2e3Ab".replace(/[a-f][1-9]/gi,"X"));
    // absxsdfXQ2XAb
    var p = /[A-z0-9_]/; //-> \w
    var p = /[^A-z0-9_]/; //-> \W
    var d = /[0-9]/ //->\d
    var d = /[^0-9]/ //->\D


    //6、练习
    //字符类 []
    console.log("absxsdfe123Ab".replace(/[abd]/,"X"));
    console.log("absxsdfe123Ab".replace(/[abd]/g,"X"));
    console.log("absxsdfe123Ab".replace(/[abd]/gi,"X"));

    // 字符类 的取反 [^]
    console.log("absxsdfe123Ab".replace(/[^abd]/,"X"));
    console.log("absxsdfe123Ab".replace(/[^abd]/g,"X"));
    console.log("absxsdfe123Ab".replace(/[^abd]/gi,"X"));

    //范围类
    console.log("12345667".replace(/[3-9]/gi,"X"));
    console.log("absxsdfe123Ab".replace(/[a-f1-9]/gi,"X"));
    console.log("absxsdfe123Ab".replace(/[a-f][1-9]/gi,"X"));//如果单独替换，则需要分组，见后续
    console.log("absxsdfe1Q2e3Ab".replace(/[a-f][1-9][A-Z]/gi,"X"));

    //思考：如何匹配 -
    console.log("2017-10-23".replace(/[0-9]/g,"X"));
    console.log("2017-10-23".replace(/[0-9-]/g,"X"));

    //关于 . 除了回车和换行符之外的所有字符
    /ab[0-9][^\r\n]/ //等效于/[ab\d.]/
    console.log("@abc@123@".replace(/@./g,"Q"));
    console.log("@abc@123@".replace(/.@/g,"Q"));

    //关于边界 ^ $ \b \B
    console.log("This is a Boy is".replace(/is/g,0));
    console.log("This is a Boy is".replace(/^is/g,0));
    console.log("This is a Boy is".replace(/is$/g,0));
    console.log("This is a Boy is".replace(/is\b/g,0));
    console.log("This is a Boy is".replace(/is\B/g,0));
    console.log("This is a Boy is".replace(/\bis/g,0));
    console.log("This is a Boy is".replace(/\Bis/g,0));


    // 7、量词
    //量词 注意*在这里是量词，不是充当通配符，充当通配符的是 .
    //? 出现0次或1次（最多出现1次）
    console.log("AaBbAb_AaaBbbAba".replace(/Aa?/g,0));
    // 0Bb0b_0aBbb0ba    Aa->0 A->0
     
    //+ 出现1次或多次（至少出现1次）
    console.log("AaBbAb_AaaBbbAba".replace(/Aa+/g,0));
    // 0BbAb_0BbbAba   Aa->0 Aaa->0

    //* 出现0次或多次（任意次）
    console.log("AaBbAb_AaaBbbAba".replace(/Aa*/g,0));
    // 0Bb0b_0Bbb0ba  A->0 Aa->0 Aaa->0

    //{n} 出现n次
    console.log("AaBbAb_AaaBbbAba".replace(/Aa{1}/g,0));
    // 0BbAb_0aBbbAba Aa->0
    console.log("AaBbAb_AaaBbbAba".replace(/Aa{2}/g,0));
    // AaBbAb_0BbbAba Aaa->0

    //{n,m} 出现n到m次
    console.log("AaBbAb_AaaBbbAba".replace(/Aa{1,2}/g,0));
    // 0BbAb_0BbbAba Aa->0 Aaa->0 

    //{n,} 出现至少n次 默认模式是贪婪模式
    console.log("AaBbAb_AaaBbbAbaAaaaaaaAaaAaaa".replace(/Aa{2,}/g,0));
    // AaBbAb_0BbbAba000
    console.log("AaBbAb_AaaBbbAbaAaaaaaaAaaAaaa".replace(/Aa{2,4}/g,0));
    // AaBbAb_0BbbAba0aa00

    //注意：0到n次的写法{0,n}而不是{,n}

    //思考：
    var reg = /d{20}\w\d?\w+\d*\w{3,5}\d{3,}/;

    // 8、贪婪和惰性
    //贪婪：尽可能多的匹配
    //惰性：尽可能少的匹配

    //  {x,} {x,}？
    var pattern = /\d{3,}/g; //贪婪 //abc$
    //var pattern = /\d{3,}?/g;//惰性 //abc$$78
    var str = "abc12345678";
    console.log(str.replace(pattern, "$"));

    //  {x,y} {x,y}？
    var pattern = /\d{3,5}/g; //贪婪 //abc$$
    //var pattern = /\d{3,5}?/g;//惰性 //abc$$78
    var str = "abc12345678";
    console.log(str.replace(pattern, "$"));

    "12345678".replace(/\d{3,6}/,'X');//默认为贪婪模式  X78
    "12345678".replace(/\d{3,6}?/,'X');//设置为非贪婪模式 在量词后加？X45678
    "12345678".replace(/\d{3,6}?/g,'X');//返回什么？'XX78'
    
    // 9、选择和分组
    //选择
    var pattern = /red|green|blue/g;
    //var str ="color:red"; //color:$
    //var str ="color:green"; //color:$
    //var str ="color:blue"; //color:$
    var str = "color:red;background:blue;";
    console.log(str);
    console.log(str.replace(pattern, "$"));
    // color:$;background:$;

    //分组  获取  编号
    var pattern = /8(.*)8a(.*)f/;
    var str = "8ggggg8abcdef";
    var arr = pattern.exec(str);
    console.log(arr);
    // ['8ggggg8abcdef', 'ggggg', 'bcde', index: 0, input: '8ggggg8abcdef', groups: undefined]
    console.log(arr[1]);//第1个分组内容 //ggggg
    console.log(arr[2]);//第2个分组内容 //bcde

    //练习
    //正则表达式的分组
    console.log("NameNameName_11111".replace(/Name{3}/,"X"));
    // NameNameName_11111 Nameee->X
    console.log("NameNameName_11111".replace(/(Name){3}/,"X"));
    // X_11111  ()进行分组 NameNameName->X

    console.log("a1b2c3d4e5".replace(/[a-z]\d{3}/,"X")); //a1b2c3d4e5
    console.log("a1b2c3d4e5".replace(/([a-z]\d){3}/,"X")); //Xd4e5
    console.log("a1b2c3d4e5".replace(/([a-z]\d){3,4}/,"X")); //Xe5
    console.log("a1b2c3d4e5".replace(/([a-z]\d){3,4}?/,"X")); //Xd4e5

    // 与分组相关的 或
    "abcdefghijk".replace(/abcde|fghijk/g,"X"); //'XX'
    "abcdefghijk_abcdehijk_abcfghijk".replace(/abc(de|fg)hijk/g,"X"); //'abcdefghijk_X_X'

    //练习：
    "xx11xx".replace(/(\bxx)|(xx\b)/g,"yy"); //'yy11yy'
    
    //将"xxabccxxdexx"替换为"yyabccxxdeyy"
    "xxabccxxdexx".replace(/(\bxx)|(xx\b)/g,"yy");

    //分组的 反向引用
    //如何将2017-10-23转成10/23/2017
    var newStr = "2017-10-23".replace(/(\d{4})-(\d{2})-(\d{2})/,"$2/$3/$1");
    console.log(RegExp.$1,RegExp.$2,RegExp.$3);
    // 2017 10 23
    console.log(newStr); 
    // 10/23/2017


</script>
</html> 